package com.ruoyi.standingbook.sanitationvehicle.service.impl;

import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.tools.constant.ERecordConstant;
import com.ruoyi.common.tools.excel.MyExcelUtil;
import com.ruoyi.common.tools.excel.base.MyExcelResult;
import com.ruoyi.common.tools.excel.listener.SanitationVehicleExcelListener;
import com.ruoyi.common.tools.utils.SerialGenerator;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.standingbook.sanitationvehicle.ItemEnum;
import com.ruoyi.standingbook.sanitationvehicle.domain.bo.SanitationVehicleBillBo;
import com.ruoyi.standingbook.sanitationvehicle.domain.bo.SanitationVehicleImportBaseBo;
import com.ruoyi.standingbook.sanitationvehicle.domain.vo.SanitationVehicleImportDetailVo;
import com.ruoyi.standingbook.sanitationvehicle.service.ISanitationVehicleBillService;
import com.ruoyi.standingbook.sanitationvehicle.service.ISanitationVehicleImportBaseService;
import com.ruoyi.standingbook.sanitationvehicle.service.ISanitationVehicleImportDetailService;
import com.ruoyi.standingbook.sanitationvehicle.service.ISanitationVehicleService;
import com.ruoyi.standingbook.v2toilet.ToiletConst;
import com.ruoyi.standingbook.v2toilet.enums.ItemStatusEnum;
import com.ruoyi.system.domain.vo.SysOssVo;
import com.ruoyi.system.service.ISysOssService;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class SanitationVehicleExcelService {
	private final ISysOssService sysOssService;

	private final ISanitationVehicleService sanitationVehicleService;
	private final ISanitationVehicleBillService sanitationVehicleBillService;
	private final ISanitationVehicleImportBaseService sanitationVehicleImportBaseService;
	private final ISanitationVehicleImportDetailService sanitationVehicleImportDetailService;

    @Value("${erecord.api.call:true}")
    private boolean callApi;
    
	/**
	 * 导入excel数据
	 *
	 * @param bo
	 * @return
	 */
	public List<String> importExcel(SanitationVehicleImportBaseBo bo) {
        List<String> errorMsgList = new ArrayList<>();
        
		// 生成批次号
		final String batchNo = SerialGenerator.generator.nextId();
		bo.setBatchNo(batchNo);

		// excel 处理
		MyExcelResult<SanitationVehicleImportDetailVo> excelResult = MyExcelUtil.getImportExcelData(batchNo,
				bo.getExcelUrl(), new SanitationVehicleExcelListener(batchNo), SanitationVehicleImportDetailVo.class,
				true);

		if (null == excelResult) {
            return null;
		}
		
        /**
         *  有解析失败就直接返回错误信息
         */
        if(!excelResult.getErrorList().isEmpty()) {
            return excelResult.getErrorList();
        }
        
		// 去掉没有处理状态的数据
		List<SanitationVehicleImportDetailVo> collect = excelResult.getList().stream()
				.filter(e -> Objects.nonNull(e.getProcessStatus())).collect(Collectors.toList());
		excelResult.setList(collect);
		
        List<SanitationVehicleImportDetailVo> list = excelResult.getList();
        if(!list.isEmpty()){
        	AtomicInteger row = new AtomicInteger(0);
        	
        	list.forEach(item->{
        		int currentRow = row.incrementAndGet();
                if (!item.getDataCheckResult().isSucess()) {
                	errorMsgList.add(String.format("第 %d 行数据检查失败，失败原因：%s", currentRow, item.getProcessMsg()));
                }
            });
        }

		// 更新主表状态
		if (excelResult.isSuccess()) {
			bo.setProcessStatus(ERecordConstant.COMMON_STATUS_SUCCESS);
		} else {
			bo.setProcessStatus(ERecordConstant.COMMON_STATUS_ERROR);
		}
		bo.setProcessMsg(excelResult.getAnalysis());
		bo.setAttachMsg(ERecordConstant.ATTACH_UPLOAD_STATUS_NO);

        if (!errorMsgList.isEmpty()) {
        	bo.setProcessMsg(analysis(excelResult));
        	sanitationVehicleImportBaseService.insertByBo(bo);
        	
        	return errorMsgList;
        }
		
		Map<String, Object> query = new HashMap<>();
		// 用管养日期和 是否已经改变选项来确定
		query.put(ToiletConst.MODIFY_KEY, ToiletConst.MODIFY_NOT);

		List<SanitationVehicleBillBo> bills = new ArrayList<>();// 异常工单
		// 填充数据
		collect.forEach(detail -> fitBillData(detail, bills, query));
		// 填充数据 END

		if (excelResult.isSuccess() && !excelResult.getList().isEmpty()) {
			if (sanitationVehicleImportBaseService.insertByBo(bo) && 
					sanitationVehicleImportDetailService.batchInsertOrUpdate(excelResult.getList())) {
				sanitationVehicleService.batchInsertOrUpdate(excelResult.getList());
				
				sanitationVehicleBillService.batchInsertOrUpdate(bills);
	            
	            if (callApi) {
	            	R<String> r = sanitationVehicleBillService.sendBills(batchNo);
	            	
	            	if (R.isError(r)) {
	            		errorMsgList.add(r.getMsg());
	            	}
	            }
			}
		}

		return errorMsgList;
	}

	private String analysis(MyExcelResult<SanitationVehicleImportDetailVo> excelResult) {
		//导入**条，成功**条，失败**条
		int count = excelResult.getList().size();
		int errorCount = excelResult.getErrorList().size() + excelResult.getValidateList().size();
		int successCount = 0;
		if (count == 0) {
			return "读取失败，未解析到数据";
		} else {
			if (errorCount == 0) {
				return StrUtil.format("导入{}条，成功 {} 条", count, successCount);
			} else if (excelResult.getErrorList().size() == 0) {
				return StrUtil.format("导入{}条，成功 {} 条，失败 {} 条", count, successCount, errorCount);
			} else {
				return StrUtil.format("导入{}条，校功 {} 条，失败 {} 条", count, successCount, errorCount);
			}
		}
	}
	
	/**
	 * 数据转换 填充订单数据
	 *
	 * @param data  厕所导入集合
	 * @param bills 工单集合
	 * @param query 待发送数据
	 */
	private void fitBillData(SanitationVehicleImportDetailVo data, List<SanitationVehicleBillBo> bills,
			Map<String, Object> query) {
		query.put(ToiletConst.QUERY_INSPECT_DATE, DateUtil.format(data.getCheckDate(), "yyyy-MM-dd"));
		JSONObject jsonObject = JSONUtil.parseObj(data);
		if (jsonObject.isEmpty())
			return;
		String imageBefore, imageAfter;
		// 为所有巡检项生产数据
		for (ItemEnum ti : ItemEnum.values()) {
			// 先设置BillItem
			SanitationVehicleBillBo billBo = new SanitationVehicleBillBo();
			billBo.setFlowCode(SerialGenerator.flowCode(null, null));
			// 根据excel中的 √ × 或 空值 判断状态是什么
			int status = jsonObject.get(ti.attr, Integer.class, true);
			switch (status) {
			case 1:
				billBo.setStatus(ItemStatusEnum.ERR.intCode);
				break;
			case 3:
				billBo.setStatus(ItemStatusEnum.OK.intCode);
				break;
			default:
				billBo.setStatus(ItemStatusEnum.NO_DATA.intCode);
				break;
			}
			billBo.setProjectName(data.getProjectName());
			billBo.setCheckDate(data.getCheckDate());
			billBo.setItem(ti.attr);
			billBo.setModifyCode(ToiletConst.MODIFY_YES);
			billBo.setSanitationVehicleId(data.getId());
			billBo.setItemText(ti.note);
			billBo.setLicensePlateNo(data.getLicensePlateNo());
			billBo.setCurrUser(data.getCheckor());
			billBo.setBatchNo(data.getBatchNo());

			// 增加巡检项 图片ID
			//imageBefore = jsonObject.getStr(ti.attr.concat(ToiletConst.EXCEL_IMAGE_BEFORE), "");
			imageBefore = jsonObject.getStr(SanitationVehicleExtendProcessService.itemNameToItemImageName(ti.attr, true), "");
			if (StringUtils.isNumeric(imageBefore)) {
				SysOssVo ossVo = sysOssService.getById(Long.valueOf(imageBefore));
				billBo.setImageBefore(ossVo.getUrl());
			}
			//imageAfter = jsonObject.getStr(ti.attr.concat(ToiletConst.EXCEL_IMAGE_AFTER), "");
			imageAfter = jsonObject.getStr(SanitationVehicleExtendProcessService.itemNameToItemImageName(ti.attr, false), "");
			if (StringUtils.isNumeric(imageAfter)) {
				SysOssVo ossVo = sysOssService.getById(Long.valueOf(imageAfter));
				billBo.setImageAfter(ossVo.getUrl());
			}
			billBo.setCreateTime(DateUtil.date());
			// 公厕ID加属性ID
			billBo.setId(SecureUtil.md5(data.getId().toString().concat(ti.attr)));
			billBo.setModified(ToiletConst.MODIFY_YES);// 可以修改
			bills.add(billBo);
		}
	}

	public String getAnalysis(MyExcelResult<SanitationVehicleImportDetailVo> excelResult) {
		// 导入**条，成功**条，失败**条
		int count = excelResult.getList().size();
		int errorCount = excelResult.getErrorList().size() + excelResult.getValidateList().size();
		int successCount = count - errorCount;
		if (count == 0) {
			return "读取失败，未解析到数据";
		} else {
			if (errorCount == 0) {
				return StrUtil.format("导入{}条，成功 {} 条", count, successCount);
			} else if (excelResult.getErrorList().size() == 0) {
				return StrUtil.format("导入{}条，成功 {} 条，失败 {} 条", count, successCount, errorCount);
			} else {
				return StrUtil.format("导入{}条，校功 {} 条，失败 {} 条", count, successCount, errorCount);
			}
		}
	}
}
